/*
 * Copyright 1999-2101 Alibaba Group.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.boot2.core.web;

import com.alibaba.fastjson.parser.DefaultJSONParser;
import com.alibaba.fastjson.parser.JSONToken;
import com.alibaba.fastjson.serializer.LongCodec;
import com.boot2.core.constant.CoreConstant;
import com.boot2.core.utils.AesUtil;
import com.boot2.core.utils.StringUtils;
import com.boot2.core.conf.UrlProperties;
import lombok.extern.apachecommons.CommonsLog;
import org.apache.commons.lang3.reflect.MethodUtils;
import org.springframework.util.Assert;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Type;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 
 * @ClassName: DecipherLongCodec
 * @description: id解密
 * @author zhangweilin
 * @date 2018年1月4日 下午2:50:23
 *
 */
@CommonsLog
public class DecipherLongCodec extends LongCodec {

	@SuppressWarnings("unchecked")
	@Override
	public <T> T deserialze(DefaultJSONParser parser, Type clazz, Object fieldName) {
		// System.out.println("fieldName: " + fieldName);
		// System.out.println("clazz: " + clazz);

		String name = parser.getContext().object.getClass().getSimpleName();
		// System.out.println("name: " + name);
		String modelClassName = StringUtils.changFirstWord(name, StringUtils.toLowerCase);// 默认情况 为当前model
		if (RequestContext.getSession() == null) {
			return super.deserialze(parser, clazz, fieldName);
		}
		Object customer = RequestContext.getSession().getAttribute(CoreConstant.customerLoginSessionKey);
		if (customer == null) {
			return super.deserialze(parser, clazz, fieldName);
		}
		String value = (String) parser.parse();
		if (StringUtils.isEmpty(value)) {
			return null;
		} else if (StringUtils.isNumber(value)) {
			return super.deserialze(parser, clazz, fieldName);
		}

		// 如果是自身的id，则直接取modelClassName,反之，从id里来取
		if ("id".equals(fieldName) || "parentId".equals(fieldName)) {

		} else if (((String) fieldName).matches(".*[iI][dD]")) {
			modelClassName = ((String) fieldName).replaceAll("[iI][dD]", "");
		} else {
			throw new IllegalArgumentException(
					"参数对【 " + fieldName + "=" + value + "】不合规范，请严格按id或parentId或modelNameId的语法命名");
		}
		// 所有者userName+当前类名（全小写）+约定密钥常量,故同一个用户。看同一个实体时，其加密后的id也不一样，这样保证与身份绑定起来，好校验
		String userName = null;
		try {
			userName = (String) MethodUtils.invokeMethod(customer, "getUserName");
			String key = userName + "_" + modelClassName + "_" + UrlProperties.aesEncryptKey;

			String idStr = AesUtil.aesDecodeWithBase64(key, value);
			Assert.isTrue(StringUtils.isNotEmpty(idStr), "无法解密参数，请确认参数是否正确，userName: " + userName + ",value: " + value
					+ ",modelName:" + modelClassName + "，很有可能是参数不合规范，请严格按id或parentId或modelNameId的语法命名");
			Long id = Long.parseLong(idStr);
			log.info("解析出来的【id】: " + id);
			return clazz == AtomicLong.class //
					? (T) new AtomicLong(id.longValue()) //
					: (T) id;

		} catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
			e.printStackTrace();
			return super.deserialze(parser, clazz, fieldName);
		}
	}

	public int getFastMatchToken() {
		return JSONToken.LITERAL_INT;
	}
}
